package com.winchain.provider.expiration.service.impl;

import com.shell.bee.acct.AcctService;
import com.shell.bee.acct.account.po.AcctBas;
import com.shell.bee.acct.account.po.AcctBkp;
import com.shell.bee.acct.account.po.AcctCard;
import com.shell.bee.acct.account.util.VirtualAcctUtil;
import com.shell.bee.acct.transaction.po.AcctTxRec;
import com.shell.bee.acct.transaction.service.AcctTxRecService;
import com.shell.bee.acct.transaction.vo.AcctInfo;
import com.shell.bee.base.exception.UnCheckMsgException;
import com.shell.bee.base.utils.DateUtil;
import com.shell.bee.base.utils.MoneyUtil;
import com.shell.bee.base.utils.SpringContextUtil;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.shell.bee.persistence.annotation.Pagination;
import com.shell.bee.persistence.model.PageLimit;
import com.shell.bee.persistence.service.impl.PersistentServiceImpl;
import com.shell.bee.persistence.transaction.Transaction;
import com.shell.bee.persistence.transaction.TransactionUtil;
import com.shell.constant.rel.AssetCode;
import com.shell.framework.command.ChainBase;
import com.shell.framework.command.CommandContext;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.framework.utils.MessageSender;
import com.shell.framework.utils.SysDateUtil;
import com.shell.governor.modules.message.keyword.ExpCreditFailedKeyWord;
import com.shell.governor.modules.message.keyword.ExpCreditKeyWord;
import com.winchain.chainbill.ChainBillUtil;
import com.winchain.chainbill.asset.biz.credit.cmd.BillAssetTranCmd;
import com.winchain.chainbill.basic.cus.po.CusRec;
import com.winchain.chainbill.basic.cus.service.CusRecService;
import com.winchain.chainbill.bill.base.po.CbDct;
import com.winchain.chainbill.bill.base.po.CbDfrl;
import com.winchain.chainbill.bill.base.po.CbHldr;
import com.winchain.chainbill.bill.base.po.CbRec;
import com.winchain.chainbill.bill.base.po.CbXfe;
import com.winchain.chainbill.bill.base.service.CbDctService;
import com.winchain.chainbill.bill.base.service.CbXfeService;
import com.winchain.chainbill.trade.service.BillAcctBlcService;
import com.winchain.chainbill.trade.service.BillAcctService;
import com.winchain.chainbill.trade.service.TradeService;
import com.winchain.provider.expiration.cmd.BillExpDebitCreditTranCmd;
import com.winchain.provider.expiration.dao.CbCreditDao;
import com.winchain.provider.expiration.exception.CreditException;
import com.winchain.provider.expiration.po.CbCredit;
import com.winchain.provider.expiration.po.CbDebit;
import com.winchain.provider.expiration.service.BillExpHldrService;
import com.winchain.provider.expiration.service.BillExpThreadService;
import com.winchain.provider.expiration.service.CbCreditService;
import com.winchain.provider.expiration.service.CbDebitService;
import com.winchain.provider.expiration.vo.BatchStats;
import com.winchain.provider.expiration.vo.CbCreditQueryVo;
import com.winchain.provider.expiration.vo.CbCreditVo;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("cbCreditService")
public class CbCreditServiceImpl extends PersistentServiceImpl<CbCredit> implements CbCreditService {
	@Autowired
	private CbCreditDao cbCreditDao;
	@Autowired
	private CusRecService cusRecService;
	@Autowired
	private BillExpHldrService billExpHldrService;
	@Autowired
	private TradeService tradeService;
	@Autowired
	private BillExpDebitCreditTranCmd billExpDebitCreditTranCmd;
	@Autowired
	private BillAssetTranCmd billAssetTranCmd;
	@Autowired
	private CbXfeService cbXfeService;
	@Autowired
	private AcctTxRecService AcctTxRecService;
	@Autowired
	private BillExpThreadService billExpThreadService;
	@Autowired
	private BillAcctService billAcctService;
	@Autowired
	private BillAcctBlcService billAcctBlcService;
	@Autowired
	private CbDebitService cbDebitService;
	@Autowired
	private CbDctService cbDctService;
	@Autowired
	private AcctService acctService;

	public int updateCreditState(String state, List<String> ids) {
		return this.cbCreditDao.updateCreditState(state, ids);
	}

	public CbCredit saveBillCredit(CbDebit debit, CbRec bill, String expDate) {
		String billState = bill.getBillState();
		CbCredit credit = null;
		if (("S005".equals(billState)) || ("S012".equals(billState)) || ("S011".equals(billState))
				|| ("S035".equals(billState))) {
			credit = saveCbCredit(debit, bill, null, expDate);
		}
		return credit;
	}

	public CbCredit saveCbCredit(CbDebit debit, CbRec bill, CbDfrl cbDfrl, String creditDate) {
		CbCredit credit = new CbCredit();
		String billId = null;
		credit.setCreditId(SystemUtil.getUUID());
		String creditType = null;
		String hldrId = null;
		String hldrName = null;
		BigDecimal amount;
		if (bill == null) {
			credit.setDebitId(null);
			credit.setCreditDate(creditDate);
			creditType = "1";
			CbXfe xfe = (CbXfe) this.cbXfeService.selectByKey(cbDfrl.getXfeId());
			hldrId = xfe.getBuyerId();
			hldrName = xfe.getBuyerNm();
			amount = cbDfrl.getDfrInt();
			billId = cbDfrl.getBillId();
		} else {
			billId = bill.getBillId();
			if (debit != null) {
				credit.setDebitId(debit.getDebitId());
			}
			credit.setCreditDate(bill.getExpDate());
			creditType = "0";
			CbHldr hldr = this.billExpHldrService.getHldrWithNewTx(billId, bill.getHldrLvl().intValue());
			hldrId = hldr.getHldrId();
			hldrName = hldr.getHldrNm();
			amount = bill.getBillAmt();
		}
		credit.setCreditType(creditType);
		credit.setBillId(billId);
		credit.setBillAmount(amount);

		credit.setCusId(hldrId);
		credit.setCusName(hldrName);
		AcctBas acct = this.billExpHldrService.getDfltSettlAcct(hldrId);
		if (acct == null) {
			this.logger.error("����[" + credit.getCusName() + "]����������������");
		} else {
			credit.setAcctNo(acct.getAcctNo());
			credit.setAcctName(acct.getAcctNm());
			credit.setBankCode(acct.getHqFiNo());
			credit.setBankName(acct.getFiNm());
		}
		credit.setCreditState("0");
		credit.setEditorId(CommonDataUtil.getUserId());
		credit.setEditTime(DateUtil.getSystemDateTime());
		save(credit);
		return credit;
	}

	private BigDecimal saveSerFeeCredit(CbRec bill, CbDebit debit, BigDecimal amout) {
		if (("S012".equals(bill.getBillState())) || ("S011".equals(bill.getBillState()))) {
			List<String> dctStates = new ArrayList();
			dctStates.add("1");
			dctStates.add("2");
			CbDct dct = this.cbDctService.selectDctByBillIdAndStates(bill.getBillId(), dctStates);
			BigDecimal serFee = dct.getSerFee();
			if ((serFee != null) && (MoneyUtil.biggerThanZero(serFee))) {
				amout = amout.subtract(serFee);

				CusRec platform = this.cusRecService.getPlatform(null);
				CbCredit credit = new CbCredit();
				credit.setCreditId(SystemUtil.getUUID());
				if (debit != null) {
					credit.setDebitId(debit.getDebitId());
				}
				credit.setCreditDate(bill.getExpDate());
				credit.setCreditType("2");
				credit.setBillId(bill.getBillId());
				credit.setBillAmount(serFee);
				credit.setCusId(platform.getCusId());
				credit.setCusName(platform.getCusName());

				AcctCard acct = this.acctService.getCard(platform.getCusId(), "0", "00", null);
				if (acct == null) {
					this.logger.error("����������������������");
					throw new UnCheckMsgException("����������������������");
				}
				credit.setAcctNo(acct.getAcctNo());
				credit.setAcctName(acct.getAcctNm());
				credit.setBankCode(acct.getHqFiNo());
				credit.setBankName(acct.getFiNm());
				credit.setBankCity(acct.getFiCityNm());
				credit.setBankProvince(acct.getFiPrvnNm());

				credit.setAcctNo(acct.getAcctNo());
				credit.setAcctName(acct.getAcctNm());
				credit.setBankCode(acct.getHqFiNo());
				credit.setBankName(acct.getFiNm());

				credit.setCreditState("0");
				credit.setEditorId(CommonDataUtil.getUserId());
				credit.setEditTime(DateUtil.getSystemDateTime());
				save(credit);
			}
		}
		return amout;
	}

	public List<CbCredit> getBillCredits(String creditDate, String grpId, String creditState, String creditType) {
		return this.cbCreditDao.getBillCredits(creditDate, grpId, creditState, creditType);
	}

	public boolean creditByDebitId(String debitId) {
		List<CbCredit> cbCredits = getBillCreditsByDebitId(debitId);
		for (final CbCredit cbCredit : cbCredits) {
			try {
				TransactionUtil.execute(new Transaction() {
					public void doInTransaction() {
						Map<String, String> result = CbCreditServiceImpl.this.creditById(cbCredit.getCreditId(), false,
								"����������������������");
						if (("S".equals(result.get("ret_code")))
								&& (("0".equals(cbCredit.getCreditType())) || ("2".equals(cbCredit.getCreditType())))) {
							CbCreditServiceImpl.this.trdQuota(cbCredit);
						}
					}
				}, new int[0]);
			} catch (Exception e) {
				e.printStackTrace();
				this.logger.error(getClass() + "��������", e);
			}
		}
		return true;
	}

	public boolean batchCreditByDebitId(String debitId, String cashId, boolean batchJob, boolean offline) {
		List<CbCredit> credits = getBillCreditsByDebitId(debitId);
		boolean[] retFlag = new boolean[1];
		retFlag[0] = true;
		for (final CbCredit credit : credits) {
			if (!"1".equals(credit.getCreditState())) {
				AcctTxRec acctTxRec = getAcctTxRec(credit, cashId);
				Map<String, String> ret = null;
				boolean creditFlag;
				if (ChainBillUtil.onlinePay()) {
					ret = this.tradeService.fire(acctTxRec);
					creditFlag = "S".equals(ret.get("ret_code"));
				} else if (offline) {
					creditFlag = true;
					this.tradeService.callback(acctTxRec);
				} else {
					creditFlag = false;
					this.tradeService.rollback(acctTxRec);
				}
				String creditState;
				if (creditFlag) {
					creditState = "1";
					this.billExpThreadService.execute(new Runnable() {
						public void run() {
							CbCreditServiceImpl.this.trdQuota(credit);
						}
					});
				} else {
					creditState = "2";
					if (batchJob) {
						sendExpCreditFailedMessage(credit);
					}
					retFlag[0] = false;
				}
				credit.setCreditState(creditState);
				credit.setEditorId(CommonDataUtil.getUserId());
				credit.setEditTime(SysDateUtil.getSystemDateTime());
				updateNotNull(credit);
			}
		}
		return retFlag[0];
	}

	public Map<String, String> creditById(String creditId, boolean batchJob, String txAbs) {
		Map<String, String> result = null;

		CbCredit credit = lockByKey(creditId);
		if ("1".equals(credit.getCreditState())) {
			this.logger.warn("Credit state has changed");
			result = new HashMap();
			result.put("ret_code", "F");
			result.put("ret_msg", "������������������������");
			return result;
		}
		result = pmt(credit, txAbs);
		if (!"S".equals(result.get("ret_code"))) {
			if (batchJob) {
				sendExpCreditFailedMessage(credit);
			}
		}
		return result;
	}

	public List<CbCreditVo> selectCreditAbnormalList(PageLimit pageLimit, CbCreditQueryVo cbCreditQueryVo) {
		String cusName = cbCreditQueryVo.getCusName();
		if (StringUtil.emptyAndNull(cusName)) {
			cusName = StringUtil.getParameterLike(cusName);
			cbCreditQueryVo.setCusName(cusName);
		}
		return this.cbCreditDao.selectCreditAbnormalList(cbCreditQueryVo);
	}

	public BatchStats<String> reCredit(String... creditIds) {
		BatchStats<String> stats = new BatchStats();
		for (String creditId : creditIds) {
			try {
				Map<String, String> result = creditById(creditId, false, "��������");
				CbCredit credit = (CbCredit) selectByKey(creditId);
				if ("S".equals(result.get("ret_code"))) {
					stats.addPassedRecord("1");
					if (("0".equals(credit.getCreditType())) || ("2".equals(credit.getCreditType()))) {
						String txSnHost = trdQuota(credit);
						stats.setTxSnHost(txSnHost);
					}
				} else {
					stats.addAbnormalRecord("2");
					String msg = (String) result.get("ret_msg");
					if (!StringUtil.emptyAndNull(msg)) {
						stats.addAbnormalMsg(msg);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
				this.logger.error(getClass() + "��������", e);
				stats.addAbnormalRecord("2");
				stats.addAbnormalMsg(e.getMessage());
			}
		}
		return stats;
	}

	public Map<String, BigDecimal> sumCreditStatsList(CbCreditQueryVo cbCreditQueryVo) {
		PageLimit limit = new PageLimit();
		limit.setDoPage(false);
		List<CbCreditVo> creditVoList = selectDebitCreditList(limit, cbCreditQueryVo);
		BigDecimal totAmt = BigDecimal.ZERO;
		for (CbCreditVo creditVo : creditVoList) {
			totAmt = totAmt.add(creditVo.getBillAmount());
		}
		Object ret = new HashMap();
		((Map) ret).put("totAmt", totAmt);
		return (Map<String, BigDecimal>) ret;
	}

	@Pagination
	public List<CbCreditVo> selectCreditList(PageLimit pageLimit, CbCreditQueryVo cbCreditQueryVo) {
		String acctNo = cbCreditQueryVo.getAcctNo();
		if (StringUtil.emptyAndNull(acctNo)) {
			acctNo = StringUtil.getParameterLike(acctNo);
			cbCreditQueryVo.setAcctNo(acctNo);
		}
		String cusName = cbCreditQueryVo.getCusName();
		if (StringUtil.emptyAndNull(cusName)) {
			cusName = StringUtil.getParameterLike(cusName);
			cbCreditQueryVo.setCusName(cusName);
		}
		String creditType = cbCreditQueryVo.getCreditType();
		List<String> creditTypes = cbCreditQueryVo.getCreditTypes();
		if ((creditTypes == null) || (creditTypes.size() == 0)) {
			creditTypes = new ArrayList();
			if (StringUtil.emptyAndNull(creditType)) {
				creditTypes.add("0");
				creditTypes.add("1");
				creditTypes.add("2");
			} else {
				creditTypes.add(creditType);
			}
			cbCreditQueryVo.setCreditTypes(creditTypes);
		}
		cbCreditQueryVo.setCreditTypes(creditTypes);
		return this.cbCreditDao.selectCreditList(cbCreditQueryVo);
	}

	@Pagination
	public List<CbCreditVo> selectDebitCreditList(PageLimit pageLimit, CbCreditQueryVo cbCreditQueryVo) {
		String finId = CommonDataUtil.getCurEntId();

		String acctNo = cbCreditQueryVo.getAcctNo();
		if (StringUtil.emptyAndNull(acctNo)) {
			acctNo = StringUtil.getParameterLike(acctNo);
			cbCreditQueryVo.setAcctNo(acctNo);
		}
		String cusName = cbCreditQueryVo.getCusName();
		if (StringUtil.emptyAndNull(cusName)) {
			cusName = StringUtil.getParameterLike(cusName);
			cbCreditQueryVo.setCusName(cusName);
		}
		String creditType = cbCreditQueryVo.getCreditType();
		List<String> creditTypes = cbCreditQueryVo.getCreditTypes();
		if ((creditTypes == null) || (creditTypes.size() == 0)) {
			creditTypes = new ArrayList();
			if (StringUtil.emptyAndNull(creditType)) {
				creditTypes.add("0");
				creditTypes.add("1");
				creditTypes.add("2");
			} else {
				creditTypes.add(creditType);
			}
			cbCreditQueryVo.setCreditTypes(creditTypes);
		}
		List<CbCreditVo> credits = this.cbCreditDao.selectDebitCreditList(cbCreditQueryVo);

		String grpId = cbCreditQueryVo.getGrpId();
		if (StringUtil.emptyAndNull(grpId)) {
			String debitId = cbCreditQueryVo.getDebitId();
			grpId = this.cbDebitService.getGrpIdByDebitId(debitId);
		}
		AcctBas finAcct = null;
		if ("batch".equals(ChainBillUtil.getExpSettleMode(grpId))) {
			finAcct = this.billExpHldrService.getCashAcct(finId);
		}
		Map<String, AcctBas> finAcctMap = new HashMap();
		CbDebit debit = null;
		for (CbCreditVo credit : credits) {
			if ("0".equals(credit.getCreditState())) {
				if ("single".equals(ChainBillUtil.getExpSettleMode(grpId))) {
					finAcct = (AcctBas) finAcctMap.get(credit.getDebitId());
					if (finAcct == null) {
						debit = (CbDebit) this.cbDebitService.selectByKey(credit.getDebitId());
						finAcct = this.billExpHldrService.getCashAcct(debit.getCusId());
						finAcctMap.put(debit.getDebitId(), finAcct);
					}
				}
				credit.setTxAcctNo(finAcct.getAcctNo());
				credit.setTxAcctName(finAcct.getAcctNm());
				credit.setTxBankName(finAcct.getHqFiNm());
			}
		}
		return credits;
	}

	public BatchStats<String> confirmCredit(String... creditIds) {
		BatchStats<String> stats = new BatchStats();
		for (String creditId : creditIds) {
			try {
				CbCredit credit = lockByKey(creditId);
				if ("1".equals(credit.getCreditState())) {
					this.logger.warn("Credit state has changed");
				}
				credit.setCreditState("5");
				updateNotNull(credit);

				stats.addPassedRecord("1");
				if (("0".equals(credit.getCreditType())) || ("2".equals(credit.getCreditType()))) {
					String txSnHost = trdQuota(credit);
					stats.setTxSnHost(txSnHost);
				}
			} catch (Exception e) {
				e.printStackTrace();
				this.logger.error(getClass() + "��������", e);
				stats.addAbnormalRecord("2");
			}
		}
		return stats;
	}

	private List<CbCredit> getBillCreditsByDebitId(String debitId) {
		CbCredit credit = new CbCredit();
		credit.setDebitId(debitId);
		return this.cbCreditDao.select(credit);
	}

	public CbCredit lockByKey(String key) {
		return this.cbCreditDao.lockByKey(key);
	}

	public Map<String, String> pmt(CbCredit credit, String txAbs) {
		AcctTxRec tran = getAcctTxRec(credit, null);
		tran.setTxAbs(txAbs);
		Map<String, String> result = null;
		String msg = null;
		if (ChainBillUtil.onlinePay()) {
			if ((VirtualAcctUtil.onVirtual())
					&& (!enoughBalance(tran.getTxAcctNo(), credit.getBillId(), credit.getBillAmount()))) {
				msg = "����[" + tran.getTxAcctNo() + "]��������";
				this.logger.warn(msg);
				result = new HashMap();
				result.put("ret_code", "F");
				result.put("ret_msg", msg);
				return result;
			}
			result = this.tradeService.fire(tran);
		} else {
			this.tradeService.rollback(tran);
			result = new HashMap();
			result.put("ret_code", "F");
		}
		boolean flag = "S".equals(result.get("ret_code"));
		String txSts;
		if (flag) {
			txSts = "S";
			tran.setTxSnHost((String) result.get("tx_sn"));

			credit.setCreditState("1");
		} else {
			txSts = "F";
			msg = (String) result.get("ret_msg");
			if (StringUtil.emptyAndNull(msg)) {
				msg = "������������";
				result.put("ret_msg", msg);
			}
			credit.setCreditState("2");
		}
		tran.setTxSts(txSts);
		this.AcctTxRecService.updateNotNull(tran);

		credit.setEditorId(CommonDataUtil.getUserId());
		credit.setEditTime(SysDateUtil.getSystemDateTime());
		updateNotNull(credit);

		return result;
	}

	private boolean enoughBalance(String acctNo, String billId, BigDecimal txAmount) {
		boolean flag = true;
		try {
			this.billAcctBlcService.getBankAcctBlc(acctNo);
		} catch (Exception e) {
			this.logger.error("��������������������");
			e.printStackTrace();
		}
		CbRec bill = this.billExpHldrService.getBill(billId);
		String grpId = bill.getGrpId();
		AcctInfo acctInfo = new AcctInfo();
		acctInfo.setAcctNo(acctNo);
		acctInfo.setAcctType("1");
		acctInfo.setCurrCode(AssetCode.CNY.name());
		acctInfo.setBkpPrdCode(grpId);
		AcctInfo bas = this.billAcctService.getAcctCardInfo(acctInfo);
		if (bas == null) {
			this.billAcctBlcService.initAcctBkp(acctNo, AssetCode.CNY.name(), grpId, null, BigDecimal.ZERO);
			flag = false;
		} else if (bas.getAvailableAmt().compareTo(txAmount) < 0) {
			flag = false;
		}
		return flag;
	}

	public String trdQuota(CbCredit credit) {
		AcctTxRec txRec = findExistAcctTxRec(credit.getCreditId());
		if (txRec != null) {
			return null;
		}
		txRec = getTrdQuotaAcctTxRec(credit);
		List<AcctTxRec> AcctTxRecs = new ArrayList();
		AcctTxRecs.add(txRec);
		if (AcctTxRecs.size() == 0) {
			return null;
		}
		CommandContext<AcctTxRec> context = new CommandContext();

		context.setValue("acctTxRecs", AcctTxRecs);
		ChainBase<AcctTxRec> chainBase = new ChainBase();

		chainBase.add(this.billExpDebitCreditTranCmd);
		chainBase.add(this.billAssetTranCmd);
		chainBase.execute(context);
		if (ChainBillUtil.onChain()) {
			Object txSnHost = context.getValue("txSnHost");
			if (txSnHost != null) {
				return (String) txSnHost;
			}
		}
		return null;
	}

	private AcctTxRec findExistAcctTxRec(String creditId) {
		AcctTxRec txRec = new AcctTxRec();
		txRec.setBizId(creditId);
		txRec.setTxSts("S");
		txRec.setCurrCode(AssetCode.XCB.name());
		txRec.setTxType("cb_trd_xcb");
		return (AcctTxRec) this.AcctTxRecService.selectOne(txRec);
	}

	public void sendExpCreditMessage(String expDate, List<CbCredit> credits) {
		if (credits.size() > 0) {
			String cusId = ((CbCredit) credits.get(0)).getCusId();

			ExpCreditKeyWord keyWord = getExpCreditKeyWord(expDate, credits);
			try {
				MessageSender.sendMessageByTmpl(SpringContextUtil.getProperty("system.code"), "MT03107", keyWord,
						cusId);
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException(e.getMessage(), e);
			}
		}
	}

	public void sendExpCreditFailedMessage(CbCredit credit) {
		String finId = getFinId(credit);
		ExpCreditFailedKeyWord keyWord = getExpCreditFailedKeyWord(credit);
		try {
			MessageSender.sendMessageByTmpl(SpringContextUtil.getProperty("system.code"), "MT03105", keyWord, finId);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage(), e);
		}
	}

	private AcctTxRec getTrdQuotaAcctTxRec(CbCredit credit) {
		AcctTxRec txRec = getCommAcctTxRec(credit);
		txRec.setTxAbs("��������");
		txRec.setTxType("cb_trd_xcb");
		txRec.setOptType("qt_red");
		txRec.setCurrCode(AssetCode.XCB.name());
		txRec.setTxChnCode("C");

		String finId = getFinId(credit);

		AcctBas txAcct = this.billExpHldrService.getChainBillAcct(credit.getCusId());
		String errMsg = "����[" + ((CusRec) this.cusRecService.selectByKey(credit.getCusId())).getCusName()
				+ "]����������������";
		if (txAcct == null) {
			throw new CreditException(errMsg);
		}
		txRec.setTxAcctNo(txAcct.getAcctNo());
		txRec.setTxAcctNm(txAcct.getAcctNm());
		txRec.setTxBankNm(txAcct.getFiNm());
		AcctBkp txAcctBkp = this.billAcctBlcService.getAcctBkp(txRec.getTxAcctNo(), txRec.getCurrCode(), null, null);
		txRec.setTxBkpId(txAcctBkp.getBkpId());

		AcctBas cpAcct = this.billExpHldrService.getTransientChainAcct(finId);
		if (cpAcct == null) {
			throw new CreditException("��������������������-����������");
		}
		txRec.setCpAcctNo(cpAcct.getAcctNo());
		txRec.setCpAcctNm(cpAcct.getAcctNm());
		txRec.setCpBankNm(cpAcct.getFiNm());
		AcctBkp cpAcctBkp = this.billAcctBlcService.getAcctBkp(txRec.getCpAcctNo(), txRec.getCurrCode(), null, null);
		txRec.setCpBkpId(cpAcctBkp.getBkpId());
		return txRec;
	}

	private String getFinId(CbCredit credit) {
		return this.billExpHldrService.getFinId(credit.getBillId());
	}

	private AcctTxRec getAcctTxRec(CbCredit credit, String cashId) {
		AcctTxRec txRec = getCommAcctTxRec(credit);

		String txType = "cb_exp_cdt";
		if ("1".equals(credit.getCreditType())) {
			txType = "ex_dly_ins";
		}
		txRec.setTxType(txType);
		txRec.setCurrCode(AssetCode.CNY.name());
		txRec.setTxChnCode("B");
		txRec.setOptType("qt_trd");

		String billId = credit.getBillId();
		CbRec bill = this.billExpHldrService.getBill(billId);
		String grpId = null;
		if ((ChainBillUtil.onlinePay()) && (VirtualAcctUtil.onVirtual())) {
			grpId = bill.getGrpId();
		}
		String focalCoId;
		if ("batch".equals(ChainBillUtil.getExpSettleMode(bill.getGrpId()))) {
			if (("0".equals(credit.getCreditType())) || ("2".equals(credit.getCreditType()))) {
				focalCoId = this.billExpHldrService.getFocalCoIdByBillId(billId);
			} else {
				focalCoId = this.billExpHldrService.getFinId(billId);
			}
		} else {
			focalCoId = cashId;
		}
		AcctBas txAcct = this.billExpHldrService.getCashAcct(focalCoId);
		if (txAcct != null) {
			txRec.setTxAcctNo(txAcct.getAcctNo());
			txRec.setTxAcctNm(txAcct.getAcctNm());
			txRec.setTxBankNm(txAcct.getFiNm());
			AcctBkp txAcctBkp = this.billAcctBlcService.getAcctBkp(txRec.getTxAcctNo(), txRec.getCurrCode(), grpId,
					null);
			txRec.setTxBkpId(txAcctBkp.getBkpId());
		}
		AcctBas cpAcct = this.billAcctService.getCard(credit.getAcctNo());
		if (cpAcct != null) {
			txRec.setCpAcctNo(cpAcct.getAcctNo());
			txRec.setCpAcctNm(cpAcct.getAcctNm());
			txRec.setCpBankNm(cpAcct.getFiNm());
			AcctBkp cpAcctBkp = this.billAcctBlcService.getAcctBkp(txRec.getCpAcctNo(), txRec.getCurrCode(), grpId,
					null);
			txRec.setCpBkpId(cpAcctBkp.getBkpId());
		}
		return txRec;
	}

	private AcctTxRec getCommAcctTxRec(CbCredit credit) {
		AcctTxRec txRec = new AcctTxRec();
		txRec.setTxId(SystemUtil.getUUID());
		txRec.setTxSn(SystemUtil.getUUID());
		txRec.setBizId(credit.getCreditId());
		txRec.setTxAmt(credit.getBillAmount());
		txRec.setTxDt(SysDateUtil.getSystemDate());
		txRec.setTxTs(SysDateUtil.getSystemDateTime());
		txRec.setTxSts("I");
		String sourceCode = SpringContextUtil.getProperty("system.code");
		txRec.setSrcCode(sourceCode);
		txRec.setDataScLvl("B");
		txRec.setTxCashFlag("N");
		txRec.setTxReqFiCls("1");
		txRec.setTxOperator("System");
		return txRec;
	}

	private ExpCreditFailedKeyWord getExpCreditFailedKeyWord(CbCredit credit) {
		ExpCreditFailedKeyWord keyWord = new ExpCreditFailedKeyWord();
		keyWord.setExpDate(DateUtil.parseDate(credit.getCreditDate(), "yyyyMMdd", "yyyy-MM-dd"));
		keyWord.setBillAmt(String.valueOf(credit.getBillAmount()));
		keyWord.setCusName(credit.getCusName());
		return keyWord;
	}

	private ExpCreditKeyWord getExpCreditKeyWord(String expDate, List<CbCredit> credits) {
		ExpCreditKeyWord keyWord = new ExpCreditKeyWord();
		keyWord.setNumber(String.valueOf(credits.size()));
		keyWord.setExpDate(DateUtil.parseDate(expDate, "yyyyMMdd", "yyyy-MM-dd"));
		keyWord.setAcctNo(((CbCredit) credits.get(0)).getAcctNo());
		keyWord.setTotAmt(getAmount(credits));
		return keyWord;
	}

	private String getAmount(List<CbCredit> credits) {
		BigDecimal totAmt = BigDecimal.ZERO;
		for (CbCredit credit : credits) {
			totAmt = totAmt.add(credit.getBillAmount());
		}
		return String.valueOf(totAmt);
	}
}
